<template>
  <span v-if="props.showText">{{ message }}</span>
  <div
    v-else
    @mouseenter="hovering = true"
    @mouseleave="hovering = false"
    style="width: 100%"
  >
    <div>
      <el-popover
        ref="popover"
        width="—"
        placement="bottom-start"
        :visible-arrow="true"
        trigger="click"
      >
        <template #reference>
          <el-input v-model="message" readonly>
            <template #suffix>
              <el-icon v-if="hovering && !inputDisabled" style="cursor: pointer;" @click.stop="clearInput">
                <CircleClose />
              </el-icon>
            </template>
          </el-input>
        </template>
        <el-row v-if="multiple" style="text-align: center;padding-top: 10px;">
           <el-button
             style="width: 100%"
             class="el-button--primary"
             @click="confirm"
           >确定</el-button>
        </el-row>

        <el-scrollbar
          wrap-class="popover-scrollbar"
          wrap-style="min-width:350px;min-height:450px;max-height:450px;"
          view-style="height:100%;"
          v-loading="loading"
          element-loading-text="数据加载中..."
          :noresize="false"
        >
          <el-tree
            ref="tree"
            node-key="id"
            :data="treeData"
            :props="treeProps"
            :default-expanded-keys="expandedData"
            :default-checked-keys="selectedData"
            :show-checkbox="multiple"
            :check-strictly="true"
            :filter-node-method="filterNode"
            :expand-on-click-node="leafSelect"
            @check="handleClick"
            @node-click="nodeClick"
          ></el-tree>
        </el-scrollbar>
      </el-popover>
    </div>
  </div>
</template>

<script setup>
import {ref, watch, onMounted, onUnmounted} from 'vue';
import {useOrganizationStore} from '@/pinia/modules/organization';
import {CircleClose} from '@element-plus/icons-vue';
import {emitter} from '@/utils/bus';
import {useDisabled} from 'element-plus';

const emit = defineEmits(['update:modelValue', 'change', 'update:name']);
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  leafSelect: {
    // 是否只有叶节点可选择
    type: Boolean,
    default: true,
  },
  multiple: {
    // 是否可以多选
    type: Boolean,
    default: false,
  },
  placeholder: {
    type: String,
    default: "",
  },
  showText: Boolean,
  text: {
    type: String,
    default: ''
  }
});

const inputDisabled = useDisabled();
const tree = ref();
const popover = ref();
const filterText = ref("");
const message = ref("");
const loading = ref(false);
const selectedData = ref(((props.modelValue || "") + "").split(","));
const expandedData = ref([]);
const treeData = ref([]);
const treeProps = ref({
  children: "children",
  label: function (data) {
    return data.text;
  }
});
const hovering = ref(false);
const organizationStore = useOrganizationStore();

const clearInput = () => {
  message.value = "";
  changeInput("");
};

const filterNode = (value, data) => {
  if (!value) return true;
  return data.text.indexOf(value) !== -1;
};

const handleClick = (data, checked) => {
  if (!props.multiple
      && checked === true
      && (!props.leafSelect
        || (props.leafSelect
          && (data.children == null || data.children.length === 0)))) {
    tree.value.setCheckedKeys([data.id]);
  }
  if (!props.multiple) {
    if (data) {
      tree.value.setCheckedNodes([data]);
      let id = data.id || "";
      if (id.indexOf("@") > 0) {
        id = id.split("@")[1];
      }
      emit("update:modelValue", id || "");
      emit("change");
    } else {
      emit("update:modelValue", "");
      emit("change");
    }
    hidePopover();
  }
};

const nodeClick = (data, node) => {
  if (data.disable === true) {
    emit("update:modelValue", "");
    emit("change");
    return;
  }

  if (props.multiple) {
    if (!props.leafSelect || (props.leafSelect && node.isLeaf)) {
      let nodes = tree.value.getCheckedNodes();
      if (props.leafSelect) {
        nodes = nodes.filter(
          (item) => item.children == null || item.children.length === 0
        );
      }

      let curNodes = nodes.filter((item) => item.id === data.id);
      if (curNodes.length > 0) {
        nodes = nodes.filter((item) => item.id !== data.id);
      } else {
        nodes.push(data);
      }
      tree.value.setCheckedNodes(nodes);
    }
  } else {
    if (!props.leafSelect || (props.leafSelect && node.isLeaf)) {
      hidePopover()
      tree.value.setCheckedNodes([data]);

      changeInput(data.id || "");
    } else {
      tree.value.setCheckedNodes([]);
    }
  }
};

const confirm = () => {
  let nodes = tree.value.getCheckedNodes();
  let multipleValue = [];
  let multipleMessage = [];
  nodes.forEach((item) => {
    if (!item.disable) {
      multipleValue.push(item.id);
      multipleMessage.push(item.data.name);
    }
  });
  message.value = multipleMessage.join(",");
  changeInput(multipleValue.join(","));
};

const changeInput = (id) => {
  hidePopover();
  emit("update:modelValue", id);
  emit("change", id);
};

const loadOrganization = async() => {
  treeData.value = await organizationStore.getOrganization();
  expandedData.value = [treeData.value && treeData.value[0] && treeData.value[0].id];
  calcValue();
};

const calcValue = () => {
  message.value = "";
  if (treeData.value == null || treeData.value.length <= 0) {
    message.value = selectedData.value.join(",");
  } else {
    let organizations = findOrganization(treeData.value, selectedData.value);
    for (let i = 0; i < organizations.length; i++) {
      if (i > 0) {
        message.value += ",";
      }
      message.value += organizations[i].text;
    }
  }

  emit("update:name", message.value);

  // 设置选中
  if (props.multiple) {
    if (tree.value !== undefined && tree.value != null) {
      tree.value.setCheckedNodes(selectedData.value);
      tree.value.setCheckedKeys(selectedData.value); // 处理首次无法选中
    }
  }
};

const findOrganization = (datas, ids) => {
  let results = [];
  if (datas === undefined || datas == null || ids === undefined || ids == null) {
    return results;
  }

  for (let i = 0; i < datas.length; i++) {
    let id = datas[i].id + "";
    if (ids.includes(id)) {
      results.push(datas[i]);
    }

    if (datas[i].children !== undefined && datas[i].children != null) {
      results = results.concat(findOrganization(datas[i].children, ids));
    }
  }

  return results;
};

const hidePopover = () => {
  popover.value && popover.value.hide()
};

watch(() => props.modelValue, (newVal) => {
  if (props.showText && props.text) {
    return;
  }

  message.value = "";
  if (tree.value) {
    tree.value.setCheckedNodes([]);
  }

  selectedData.value = ((newVal || "") + "").split(",");
  if (selectedData.value.length <= 0) {
    return;
  }

  calcValue();
});

watch(() => props.text, (newVal) => {
  message.value = newVal;
});

watch(() => filterText.value, (newVal) => {
  tree.value.filter(newVal);
});

onMounted(() => {
  if (props.showText && props.text) {
    message.value = props.text;
  } else {
    loadOrganization();
    emitter.on('organization.change', () => {
      loadOrganization();
    });
  }
});

onUnmounted(() => {
  emitter.off('organization.change');
});
</script>